package com.basic.im.dao.impl;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.mongodb.Mongo;
import com.mongodb.client.MapReduceIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.basic.common.model.PageResult;
import com.basic.commons.thread.ThreadUtils;
import com.basic.im.comm.constants.KConstants;
import com.basic.im.comm.utils.StringUtil;
import com.basic.im.common.MultipointSyncUtil;
import com.basic.im.constants.DBConstants;
import com.basic.im.friends.dao.FriendsDao;
import com.basic.im.friends.entity.Friends;
import com.basic.im.friends.entity.NewFriends;
import com.basic.im.friends.service.FriendsRedisRepository;
import com.basic.im.repository.MongoRepository;
import com.basic.im.user.dao.AuthKeysDao;
import com.basic.im.user.entity.User;
import com.basic.im.user.event.KeyPairChageEvent;
import com.basic.im.user.service.UserCoreService;
import com.basic.im.utils.FirstCharUtil;
import com.basic.im.utils.MongoUtil;
import com.basic.mongodb.wrapper.QueryWrapper;
import com.basic.mongodb.wrapper.UpdateWrapper;
import com.basic.utils.DateUtil;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.CommandLineRunner;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;

import java.util.*;
import java.util.stream.Collectors;

import static com.basic.im.comm.constants.KConstants.*;

@Repository
public class FriendsDaoImpl extends MongoRepository<Friends, ObjectId> implements FriendsDao , CommandLineRunner {

    @Autowired
    private FriendsRedisRepository firendsRedisRepository;

    @Autowired
    private UserCoreService userCoreService;

    @Autowired
    private AuthKeysDao authKeysDao;

    @Override
    public Class<Friends> getEntityClass() {
        return Friends.class;
    }

    @Autowired
    @Qualifier(value = "mongoTemplateFriends")
    private MongoTemplate mongoTemplateFriends;


    @Autowired
    @Qualifier(value = "mongoNewFriends")
    private MongoTemplate mongoNewFriends;

    @Override
    public MongoTemplate getDatastore() {
        return mongoTemplateFriends;
    }

    /**
     * 获取 分库  分表 表名  分表 逻辑需要继承实现
     * 分表 的类 必须实现 这个方法
     *
     * @param userId
     * @return
     */
    @Override
    public String getCollectionName(int userId) {
        int remainder = 0;
        if (userId > MIN_USERID) {
            remainder = userId / KConstants.DB_REMAINDER.FIRENDS;
        }
        return String.valueOf(remainder);
    }

    @Override
    public String getCollectionName() {
        return DBConstants.FRIENDSDBNAME;
    }

    @Override
    public void run(String... args) throws Exception {
        ThreadUtils.executeInThread(obj->{
            mongoTemplateFriends.getCollectionNames().forEach(name->{
                MongoCollection<Document> collection = mongoTemplateFriends.getCollection(name);
                if(DB_INDEX_COUNT< collection.countDocuments()){
                    collection.createIndex(new Document("userId",1).append("toUserId",1).append("status",1).append("createTime",1));

                    collection.createIndex(new Document("userId",1));
                    collection.createIndex(new Document("userId",1).append("blacklist",1));
                    collection.createIndex(new Document("userId",1).append("toUserId",1)
                            .append("status",1).append("blacklist",1).append("isBeenBlack",1));
                }
            });

            mongoNewFriends.getCollectionNames().forEach(name->{
                MongoCollection<Document> collection = mongoNewFriends.getCollection(name);
                if(DB_INDEX_COUNT< collection.countDocuments()){
                    collection.createIndex(new Document("userId",1).append("createTime",1));

                    collection.createIndex(new Document("userId",1).append("modifyTime",1));
                }
            });
        });



    }

    public Query createQuery(int userId, int toUserId) {
        Query query = createQuery("userId", userId);
        addToQuery(query, "toUserId", toUserId);
        return query;
    }

    public Query createQuery(int userId) {
        Query query = createQuery("userId", userId);
        return query;
    }

    @Override
    public Friends deleteFriends(int userId, int toUserId) {

        Query query = createQuery("userId", userId);
        addToQuery(query, "toUserId", toUserId);

        return getDatastore().findAndRemove(query, getEntityClass(), getCollectionName(userId));
    }

    @Override
    public void deleteFriends(int userId) {

        List<Integer> list = queryFollowId(userId);
        list.forEach(toUserId -> {
            deleteFriends(toUserId, userId);
            firendsRedisRepository.deleteFriends(toUserId);
            firendsRedisRepository.deleteFriendsUserIdsList(toUserId);
        });

        Query query = createQuery("userId", userId);
        deleteByQuery(query, getCollectionName(userId));
        firendsRedisRepository.deleteFriends(userId);
        firendsRedisRepository.deleteFriendsUserIdsList(userId);
    }


    @Override
    public Friends getFriends(int userId, int toUserId) {
        Query query = createQuery(userId, toUserId);
        Friends friends = findOne(query, getCollectionName(userId));
        Query toQuery = createQuery(toUserId, userId);

        Friends tofriends = findOne(toQuery, getCollectionName(toUserId));
        if (null == friends)
            return friends;
        else if (null == tofriends)
            friends.setIsBeenBlack(0);
        else {
            friends.setIsBeenBlack(tofriends.getBlacklist());
        }
        return friends;
    }

    @Override
    public List<Friends> queryBlacklist(int userId, int pageIndex, int pageSize) {
        Query query = createQuery(userId);
        addToQuery(query, "blacklist", 1);
        return queryListsByQuery(query, pageIndex, pageSize, getCollectionName(userId));
    }


    @Override
    public List<Friends> queryFriendsList(int userId, int status, int pageIndex, int pageSize) {
        return queryFriendsList(userId, status, null,null,null,pageIndex, pageSize,false);
    }

    @Override
    public List<Friends> queryFriendsList(Integer userId, Integer status, Integer userType, List<Integer> notInUserIds,String keyword,int pageIndex, int pageSize,Boolean isOrder) {
        Query query = createQuery(userId);
        if (ZERO < status) {
            addToQuery(query, "status", status);
        } else {
            query.addCriteria(Criteria.where("status").ne(0));
        }
        if (ObjectUtil.isNotNull(userType)){
            query.addCriteria(Criteria.where("toUserType").is(userType));
        }

        if (CollectionUtil.isNotEmpty(notInUserIds)){
            query.addCriteria(Criteria.where("toUserId").nin(notInUserIds));
        }

        if (StrUtil.isNotBlank(keyword)){
            keyword = MongoUtil.tranKeyWord(keyword);
            query.addCriteria(new Criteria().orOperator(Criteria.where("remarkName").regex(keyword),Criteria.where("toNickname").regex(keyword)));
        }

        if (ObjectUtil.isNotNull(isOrder) && isOrder){
            query.with(Sort.by(Sort.Order.asc("orderKey"),Sort.Order.asc("remarkName"),Sort.Order.asc("toNickname")));
        }
        if (ZERO != pageSize) {
            query.skip(0*pageIndex).limit(pageSize);
            //query.with(createPageRequest(pageIndex, pageSize));
        }


        return queryListsByQuery(query, getCollectionName(userId));
    }

    @Override
    public List<Integer> queryFollowId(int userId) {
        Query query = createQuery(userId);
        query.addCriteria(Criteria.where("status").ne(0));
        query.fields().include("toUserId");
        List<Integer> result = getDatastore().findDistinct(query, "toUserId", getCollectionName(userId), Integer.class);
        return result;
    }

    @Override
    public List<Friends> queryFriends(int userId) {
        Query query = createQuery(userId);
        addToQuery(query, "status", Friends.Status.Friends);
        query.addCriteria(Criteria.where("blacklist").ne(1));
        query.addCriteria(Criteria.where("isBeenBlack").ne(1));
        return queryListsByQuery(query, getCollectionName(userId));
    }

    @Override
    public List<Integer> queryFriendUserIdList(int userId) {
        Query query = createQuery(userId);
        addToQuery(query, "status", Friends.Status.Friends);
        query.addCriteria(Criteria.where("blacklist").ne(1));
        query.addCriteria(Criteria.where("isBeenBlack").ne(1));

        query.fields().include("toUserId");

        return getDatastore().findDistinct(query, "toUserId", getCollectionName(userId), Integer.class);
    }

    @Override
    public PageResult<Friends> queryFollowByKeyWord(int userId, int status, String keyWord, int pageIndex, int pageSize) {
        Query q = createQuery(userId);
        if (0 < status) {
            addToQuery(q, "status", status);
        }
        if (!StringUtil.isEmpty( keyWord)) {

            Criteria criteria = createCriteria().orOperator(containsIgnoreCase("toNickname",keyWord));
            q.addCriteria(criteria);
        }
        PageResult<Friends> result = new PageResult<>();
        result.setCount(count(q,getCollectionName(userId)));
        result.setData(queryListsByQuery(q, pageIndex, pageSize, getCollectionName(userId)));
        return result;
    }

    @Override
    public List<Friends> queryAllFriends(Integer userId) {
        return getEntityListsByKey("userId", userId, getCollectionName(userId));
    }
    @Override
    public long queryFriendsCount(Integer userId) {
       /* return count("userId", userId, getCollectionName(userId));*/
        return 1;
    }

    @Override
    public List<Friends> friendsOrBlackList(int userId, String type) {
        Query query = createQuery(userId);
        if ("friendList".equals(type)) {  //返回好友和单向关注的用户列表
            query.addCriteria(Criteria.where("status").ne(Friends.Status.Stranger));
            query.addCriteria(Criteria.where("blacklist").ne(1));
            //返回非陌生人列表(好友和单向关注)
            //排除加入黑名单的用户
        } else if ("blackList".equals(type)) { //返回黑名单的用户列表
            addToQuery(query, "blacklist", 1);
        }
        return queryListsByQuery(query, getCollectionName(userId));
    }

    @Override
    public List<Integer> friendsOrBlackUserIdList(int userId, String type) {
        Query query = createQuery(userId);
        if ("friendList".equals(type)) {  //返回好友和单向关注的用户列表
            query.addCriteria(Criteria.where("status").ne(Friends.Status.Stranger));
            query.addCriteria(Criteria.where("blacklist").ne(1));
            //返回非陌生人列表(好友和单向关注)
            //排除加入黑名单的用户
        } else if ("blackList".equals(type)) { //返回黑名单的用户列表
            addToQuery(query, "blacklist", 1);
        }
        return distinct(getCollectionName(userId),"toUserId",query,Integer.class);
    }

    @Override
    public Object saveFriends(Friends friends) {
        String chatRecordTimeOut = userCoreService.getSettings(friends.getUserId()).getChatRecordTimeOut();
        friends.setChatRecordTimeOut(Double.parseDouble(chatRecordTimeOut));
        // 设置排序 key
        if (StrUtil.isBlank(friends.getOrderKey())){
            friends.setOrderKey(FirstCharUtil.first(StrUtil.isNotBlank(friends.getRemarkName()) ? friends.getRemarkName() : friends.getToNickname()));
        }
        // 设置通讯号
        if(StrUtil.isBlank(friends.getAccount())){
            User user = userCoreService.getUser(friends.getToUserId());
            if (ObjectUtil.isNotNull(user)){
                friends.setAccount(user.getAccount());
            }
        }
        return getDatastore().save(friends, getCollectionName(friends.getUserId()));
    }

    @Override
    public Friends updateFriends(Friends friends) {
        Query query = createQuery(friends.getUserId(), friends.getToUserId());

        Update ops = createUpdate();
        if (null != friends.getBlacklist()) {
            ops.set("blacklist", friends.getBlacklist());
        }
        if (null != friends.getIsBeenBlack()) {
            ops.set("isBeenBlack", friends.getIsBeenBlack());
        }
        if (null != friends.getStatus()) {
            ops.set("status", friends.getStatus());
        }
        if (!StringUtil.isEmpty(friends.getToNickname())) {
            ops.set("orderKey", FirstCharUtil.first(friends.getToNickname()));
            ops.set("toNickname", friends.getToNickname());
        }
		/*if (!StringUtil.isEmpty(friends.getRemarkName()))
			ops.set("remarkName", friends.getRemarkName());*/
        if (0 != friends.getChatRecordTimeOut()) {
            ops.set("chatRecordTimeOut", friends.getChatRecordTimeOut());
        }
        if (null != friends.getToFriendsRole()) {
            ops.set("toFriendsRole", friends.getToFriendsRole());
        }
        if (0 != friends.getToUserType()) {
            ops.set("toUserType", friends.getToUserType());
        }

        if (StrUtil.isNotBlank(friends.getOrderKey())){
            ops.set("orderKey", friends.getOrderKey());
        }
        if (StrUtil.isNotBlank(friends.getAccount())){
            ops.set("account", friends.getAccount());
        }
        ops.set("modifyTime", DateUtil.currentTimeSeconds());
        return getDatastore().findAndModify(query, ops, getEntityClass(), getCollectionName(friends.getUserId()));
    }

    @Override
    public void updateFriends(int userId, int toUserId, Map<String, Object> map) {
        Query query = createQuery();
        if (0 != userId) {
            addToQuery(query, "userId", userId);
        }
        if (0 != toUserId) {
            addToQuery(query, "toUserId", toUserId);
        }
        Update ops = createUpdate();
        map.forEach(ops::set);
        update(query, ops, getCollectionName(userId));
    }

    @Override
    public void updateFriendsAttribute(int userId, int toUserId, String key, Object value) {
        Query query = createQuery();
        if (0 != userId) {
            addToQuery(query, "userId", userId);
        }
        if (0 != toUserId) {
            addToQuery(query, "toUserId", toUserId);
        }
        Update ops = createUpdate().set(key, value);
        if (0 != userId) {
            update(query, ops, getCollectionName(userId));
        } else {
            getDatastore().getCollectionNames().forEach(name -> update(query, ops, name));
        }
    }

    @Override
    public void updateMsgKeyPair(KeyPairChageEvent event) {
        Query query = createQuery("toUserId", event.getUserId());
        Update ops = createUpdate().set("dhMsgPublicKey", event.getDhMsgPublicKey());
        ops.set("rsaMsgPublicKey",event.getRsaMsgPublicKey());

        getDatastore().getCollectionNames().forEach(name -> update(query, ops, name));

    }
    public void syncUpdateMsgKeyPair(Integer toUserId,String rsaMsgPublicKey,String dhMsgPublicKey) {
        Query query = createQuery("toUserId", toUserId);
        addToQuery(query,"version",null);

        Update ops = createUpdate().set("dhMsgPublicKey", dhMsgPublicKey);
        ops.set("rsaMsgPublicKey",rsaMsgPublicKey);

        ops.set("version",1);

        getDatastore().getCollectionNames().forEach(name -> update(query, ops, name));


    }

    @Override
    public Friends updateFriendsReturn(int userId, int toUserId, Map<String, Object> map) {
        Query query = createQuery(userId, toUserId);
        Update ops = createUpdate();
        map.forEach(ops::set);
        return getDatastore().findAndModify(query, ops, getEntityClass(), getCollectionName(userId));
    }

    @Override
    public void updateFriendsEncryptType(int userId, int toUserId, byte type) {
        Query query = createQuery(userId, toUserId);
        Update ops = createUpdate();
        ops.set("encryptType", type);
        update(query, ops, getCollectionName(userId));
    }

    @Override
    public void updatePhoneRemark(int userId, int toUserId, String phoneRemark) {
        Query query = createQuery(userId, toUserId);
        String collectionName = getCollectionName(userId);
        Friends one = findOne(query,collectionName);
        // 陌生人备注
        if (null == one) {
            // 添加陌生人
            Friends friends = new Friends();
            friends.setUserId(userId);
            friends.setToUserId(toUserId);
            friends.setPhoneRemark(phoneRemark);
            friends.setStatus(Friends.Status.Stranger);
            friends.setCreateTime(DateUtil.currentTimeSeconds());
            getDatastore().save(friends, collectionName);
        }
        Update ops = createUpdate();
        ops.set("phoneRemark", phoneRemark);
        update(query, ops, collectionName);
    }

    @Override
    public List<Friends> queryBlacklistWeb(int userId, int pageIndex, int pageSize) {
        Query query = createQuery(userId);
        addToQuery(query, "blacklist", 1);

        return queryListsByQuery(query, pageIndex, pageSize, getCollectionName(userId));
    }


    @Override
    public PageResult<Friends> consoleQueryFollow(int userId, int toUserId, int status, int page, int limit) {
        PageResult<Friends> result = new PageResult<Friends>();
        Query query = createQuery(userId);
        if (0 < status)
            addToQuery(query, "status", status);
        query.addCriteria(Criteria.where("status").ne(0));
        if (0 != toUserId)
            addToQuery(query, "toUserId", toUserId);
        query.addCriteria(Criteria.where("toUserId").ne(10000));
        descByquery(query, "createTime");
        // 系统号好友不返回
        result.setCount(getFriendsCount(userId));
        result.setData(queryListsByQuery(query, page, limit, 1, getCollectionName(userId)));

        return result;
    }


    @Override
    public Friends updateFriendRemarkName(Integer userId, Integer toUserId, String remarkName, String describe) {
        Query query = createQuery(userId, toUserId);
        if (userCoreService.isOpenMultipleDevices(userId)) {
            MultipointSyncUtil.multipointLoginUpdateUserInfo(userId, userCoreService.getNickName(userId), toUserId, userCoreService.getNickName(toUserId), 1);
        }
        Friends one = findOne(query, getCollectionName(userId));
        // 陌生人备注
        if (null == one) {
            // 添加陌生人
            Friends friends = new Friends();
            friends.setUserId(userId);
            friends.setToUserId(toUserId);
            friends.setRemarkName(remarkName);
            friends.setStatus(Friends.Status.Stranger);
            friends.setCreateTime(DateUtil.currentTimeSeconds());
            friends.setDescribe(describe); // 描述
            friends.setOrderKey(FirstCharUtil.first(StrUtil.isNotBlank(friends.getRemarkName()) ? friends.getRemarkName() : friends.getToNickname()));
            getDatastore().save(friends, getCollectionName(userId));
            return friends;
        } else {
            Update ops = createUpdate();
            ops.set("modifyTime", DateUtil.currentTimeSeconds());
            if (StrUtil.isBlank(remarkName)) {
                ops.set("remarkName", StrUtil.EMPTY);
                ops.set("orderKey",FirstCharUtil.first(one.getToNickname()));
            } else {
                ops.set("remarkName", remarkName);
                ops.set("orderKey",FirstCharUtil.first(remarkName));
            }
            // 描述
            ops.set("describe", describe);
            // 维护reids好友数据
            firendsRedisRepository.deleteFriends(userId);
            return getDatastore().findAndModify(query, ops, getEntityClass(), getCollectionName(userId));
        }
    }

    @Override
    public List<Object> getAddFriendsCount(long startTime, long endTime, String mapStr, String reduce) {
        List<Object> countData;
        Document queryTime = new Document("$ne", null);

        if (startTime != 0 && endTime != 0) {
            queryTime.append("$gt", startTime);
            queryTime.append("$lt", endTime);
        }

        Document query = new Document("createTime", queryTime);

        //获得用户集合对象

        List<String> collectionList = getCollectionList();
        MongoCollection<Document> collection;
        MapReduceIterable<Document> mapReduceIter;
        MongoCursor<Document> iterator = null;
        Double value;
        String id;
        //Map<String, Double> map = new HashMap<String, Double>();
        Map<String, Double> map =new TreeMap<>();
        for (String str : collectionList) {
            collection = getDatastore().getCollection(str);
            mapReduceIter = collection.mapReduce(mapStr, reduce);
           try {
               iterator=mapReduceIter.filter(query).iterator();
            while (iterator.hasNext()) {
                Document obj = iterator.next();
                id = (String) obj.get("_id");
                value = (Double) obj.get("value");
                if (null != map.get(id)) {
                    map.put(id, map.get(id) + value);
                } else {
                    map.put(id, value);
                }

            }
           }finally {
               if(null!=iterator){
                   iterator.close();
               }
           }

        }
        countData = new ArrayList<>(map.entrySet());
        return countData;
    }

    @Override
    public List<NewFriends> getNewFriendsList(int userId, int pageIndex, int pageSize) {
        Query query = createQuery("userId", userId + "");
        query.with(Sort.by(Sort.Order.desc("modifyTime")));
        query.with(PageRequest.of(pageIndex, pageSize));
        return mongoNewFriends.find(query, NewFriends.class, getCollectionName(userId));
    }

    /** 不分页 获取从上一个月第一天至今的新朋友数据  **/
    @Override
    public List<NewFriends> getLastNewFriendsList(int userId) {
        Query query = createQuery("userId", userId + "");
        query.with(Sort.by(Sort.Order.desc("modifyTime")));
        query.addCriteria(Criteria.where("modifyTime").gte(DateUtil.getLastMonthMorning()));
        //query.with(PageRequest.of(pageIndex, pageSize));
        return mongoNewFriends.find(query, NewFriends.class, getCollectionName(userId));
    }


    @Override
    public NewFriends getNewFriendLast(int userId, int toUserId){
        Query query = createQuery("userId",userId + "");
        addToQuery(query,"toUserId",toUserId+"");
        descByquery(query,"createTime");
        return mongoNewFriends.findOne(query,NewFriends.class,getCollectionName(userId));
    }

    @Override
    public long getFriendsCount(int userId) {
        Query query = createQuery(userId);
        return count(query, getCollectionName(userId));
    }

    @Override
    public long queryAllFriendsCount() {
        long count = 0;
        for (String name : getCollectionList()) {
            count += getDatastore().getCollection(name).countDocuments();
        }
        return count;
    }

    @Override
    public boolean getFriendIsNoPushMsg(int userId, int toUserId) {
        Query query = createQuery(userId, toUserId);
        addToQuery(query,"offlineNoPushMsg",1);
        Friends friends = findOne(query, getCollectionName(userId));
        return null != friends;
    }

    @Override
    public void setHideChatSwitch(int userId, int toUserId, byte hideChatSwitch) {
        updateFirst(
                QueryWrapper.query(Friends::getUserId,userId).eq(Friends::getToUserId,toUserId).build(),
                UpdateWrapper.update(Friends::getHideChatSwitch,hideChatSwitch).set(Friends::getModifyTime, com.basic.im.comm.utils.DateUtil.currentTimeSeconds()).build(),
                getCollectionName(userId)
        );
    }

    @Override
    public void updateHiding(int userId, int hiding) {
        mongoTemplateFriends.getCollectionNames().forEach(name-> update(QueryWrapper.query(Friends::getToUserId,userId).build(),UpdateWrapper.update(Friends::getHiding,hiding).build(),name));
    }

    @Override
    public List<Friends> queryBlackList(Integer userId) {
        Query query = QueryWrapper.query(Friends::getUserId, userId).eq(Friends::getIsBeenBlack, Friends.Blacklist.Yes).build();
        return queryListsByQuery(query,getCollectionName(userId));
    }

    @Override
    public List<Friends> queryFriendsByToUserId(int userId) {
        return queryListsByQuery(QueryWrapper.query(Friends::getToUserId, userId).build(),getCollectionName(userId));
    }

    @Override
    public void updateFriend(ObjectId id,int userId, Map<String, Object> map) {
        Query query = createQuery("_id",id);
        Update ops = createUpdate();
        map.forEach((key,value)->{
            ops.set(key,value);
        });
        update(query,ops,getCollectionName(userId));
    }

    @Override
    public void setFriendsSendMsgState(Integer userId, Integer toUserId, Byte isSendMsgState) {
        Query query = createQuery(userId,toUserId);
        Update ops = createUpdate();
        ops.set("isSendMsgState",isSendMsgState);
        getDatastore().updateFirst(query,ops,getCollectionName(userId));
    }

    /**
     * 查询设置了消息加密的好友ID列表
     * @param userId
     * @return
     */
    @Override
    public List<Integer> queryEncryptFriendUserIdList(Integer userId) {
        Query query = createQuery(userId);

       /* query.addCriteria(createCriteria()
                .orOperator(Criteria.where("userId").is(userId),Criteria.where("toUserId").is(userId)
                ));*/

        query.addCriteria(Criteria.where("encryptType").gt(0));

        return distinct(getCollectionName(userId),"toUserId",query,Integer.class);

    }

    @Override
    public void cleanAndupdateOldData() {
        cleanDleteEdUserData();

        syncUserAccount();

        syncFriendMsgKey();
    }

    public void cleanDleteEdUserData(){

        long start=System.currentTimeMillis();
        logger.info("cleanDleteEdUserData start ==================>");

        Query query1 = createQuery();
        List<Integer> toUserId = distinct("toUserId", query1, Integer.class);
        for (Integer userId : toUserId) {
            if(null==userCoreService.getUserByDB(userId)){
                logger.info("用户不存在删除用户 {}",userId);
                ThreadUtils.executeInThread((obj)->{
                    deleteFriends(userId);
                });

            }

        }
        logger.info("cleanDleteEdUserData end  ==================> {} 秒 ",(System.currentTimeMillis()-start)/1000);


    }
    public void syncUserAccount(){
        try {
            long start=System.currentTimeMillis();
            logger.info("syncUserAccount start ==================>");

            Query query1 = createQuery();
            query1.addCriteria(Criteria.where("account").is(null));

            List<Integer> toUserIdList = distinct("toUserId", query1, Integer.class);

            logger.info("syncUserAccount 需要同步的数据 {} 条 ",toUserIdList.size());
            String account=null;
            for (Integer userId : toUserIdList) {
                account=userCoreService.queryUserAccount(userId);
                if(null==account){
                    continue;
                }
                Query query = createQuery("toUserId",userId);
                Update update=createUpdate();
                update.set("account",account);
                ThreadUtils.executeInThread((obj)->{
                    getDatastore().getCollectionNames().forEach(name -> update(query, update, name));
                });


            }
            logger.info("syncUserAccount end  ==================> {} 秒 ",(System.currentTimeMillis()-start)/1000);
        }catch (Exception e){
            logger.error(e.getMessage(),e);
        }


    }

    public void syncFriendMsgKey(){
        long start=System.currentTimeMillis();
        logger.info("syncFriendMsgKey start ==================>");


        List<Integer> userIdList = authKeysDao.queryIsRsaAccountUserIdList();
        logger.info("syncFriendMsgKey 需要同步的数据 {} 条 ",userIdList.size());
        ThreadUtils.executeInThread((obj)->{
            for (Integer userId : userIdList) {
                    Document  document = authKeysDao.queryMsgAndDHPublicKey(userId);
                    Document  rsaDocument=null;
                    Document  dhDocument=null;
                    if(null!=document) {
                        rsaDocument= (Document) document.get("msgRsaKeyPair");
                        dhDocument= (Document) document.get("msgDHKeyPair");
                        syncUpdateMsgKeyPair(userId,
                                rsaDocument.getString("publicKey"),
                                dhDocument.getString("publicKey"));
                    }
            }
        });
        logger.info("syncFriendMsgKey end  ==================> {} 秒 ",(System.currentTimeMillis()-start)/1000);
    }
}
